package com.fare.taluo.util.excel.engine.operate.impl;

import java.io.OutputStream;
import java.util.List;
import java.util.Map;

import jxl.Workbook;
import jxl.write.Label;
import jxl.write.WritableCell;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import jxl.write.WriteException;
import jxl.write.biff.RowsExceededException;

import com.fare.taluo.util.excel.engine.module.ExcelCellFormat;
import com.fare.taluo.util.excel.engine.module.ExcelModel;
import com.fare.taluo.util.excel.engine.module.Model;
import com.fare.taluo.util.excel.engine.module.PropertyModel;
import com.fare.taluo.util.excel.engine.module.SheetData;
import com.fare.taluo.util.excel.engine.module.SheetModel;
import com.fare.taluo.util.excel.engine.operate.IExcelWrite;
import com.fare.taluo.util.excel.util.ExcelOperationUtils;
import com.fare.taluo.util.excel.util.StringUtils;


public class ExcelWriteImpl implements IExcelWrite {
	
	/**
	 * 向excel表中写数入数据
	 * @param moduleName: 配置文件中的excel元素的id
	 * @param dataMap ： 要写入的数据
	 * @param contextMap ： 上下文map，用来替换配置文件中的表达式
	 * @param outputStream
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public void writeExcelNoCalculate(String moduleName,
			Map<String, List> dataMap, Map<String, String> contextMap,
			OutputStream outputStream) throws Exception {
		ExcelModel excelModel = (ExcelModel) Model.getInstance().getMap().get(
				moduleName);		
		WritableWorkbook wwb = null;
		try {
			wwb = Workbook.createWorkbook(outputStream);
			List<SheetModel> sheetModels = excelModel.getSheets();
			for (int ii = 0; ii < sheetModels.size(); ii++) {
				SheetModel sheetModel = sheetModels.get(ii);
				WritableSheet sheet = wwb.createSheet(StringUtils.replaceByContextMap(contextMap,sheetModel.getName()), ii);
				processSheet(dataMap, contextMap, sheetModel, sheet);
				//update xsf 2011-9-13 增加统一异步导出的进度百分比功能
//				JobExportData.changeProcess();
			}			
			wwb.write();
		} finally {
			closeResource(outputStream, wwb);
		}
	}

	/**
	 * 生成sheet中的数据
	 * @param dataMap
	 * @param contextMap
	 * @param sheetDatas
	 * @param sheet
	 * @throws Exception
	 * @throws WriteException
	 * @throws RowsExceededException
	 */
	@SuppressWarnings("unchecked")
	private void processSheet(Map<String, List> dataMap,
			Map<String, String> contextMap, SheetModel sheetModel,
			WritableSheet sheet) throws Exception, WriteException,
			RowsExceededException {
		List<SheetData> sheetDatas = sheetModel.getDatas();		
		int k = 0;	
		for (int jj = 0; jj < sheetDatas.size(); jj++) {
			SheetData sheetData = sheetDatas.get(jj);
			int startRow = 0;
			int startColumn = 0;
			if (!StringUtils.isEmpty(sheetData.getStartRow())) {
				k = startColumn = Integer.parseInt(sheetData
						.getStartRow());
			}
			if (!StringUtils.isEmpty(sheetData.getStartColumn())) {
				startColumn = Integer.parseInt(sheetData
						.getStartColumn());
			}
			int startLine = k;
			// 添加数据
			k = fillData(k, startColumn,
					dataMap.get(sheetData.getId()), sheet, sheetData, contextMap);
			PropertyModel pm = sheetData.getPropertyModels().get(0);
			// 添加序号列
			if ("true".equalsIgnoreCase(sheetData.getNeedIndex())) {
				int temp=1;
				if (dataMap.get(sheetData.getId()) != null
						&& (k - startLine) == dataMap.get(sheetData.getId())
								.size()) {// 在sheetData元素中没有输出title数据
					temp = 0;
				} else {
					sheet.addCell(new Label(startColumn, startRow + startLine,
							pm.getTitle(), new ExcelCellFormat()
									.getCellFormat(pm.getHeaderStyleMap())));
				}
				
				for (int i = startLine + temp, j = 1; i < k; i++) {
					sheet.addCell(new jxl.write.Number(startColumn, startRow + i,
							(j++), new ExcelCellFormat()
							.getCellFormat(pm.getDataStyleMap())));
				}
			}
			
			//ExcelOperationUtils.setSheetFormat(sheet,sheetModel);
		
		}
	}
	
	
	

	/**
	 * 向表中填充数据
	 * 
	 * @param list
	 *            ：数据源
	 * @param sheet
	 * @param lineNum
	 *            ：开始的行号
	 * @param metalist
	 *            ：配置的表头信息
	 * @return
	 * @throws Exception
	 * @throws WriteException
	 * @throws RowsExceededException
	 */
	private int fillData(int lineNum, int colNum, List<Object> list,
			WritableSheet sheet, SheetData sheetData,
			Map<String, String> contextMap) throws Exception{
		// 设置表头
		int startCol = colNum;// 填充单元格的开始列
		//int startRow;// 填充单元格的开始列
		List<PropertyModel>  metalist = sheetData.getPropertyModels();		
		//if(StringUtils.isTrue(sheetData.getShowTitle())){//是否显示表头
			lineNum = fillTitle(lineNum, sheet, metalist, contextMap, startCol);	
		//}	
		if (list == null) {
			return lineNum;
		}
		WritableCell cell;	// 开始填充数据	
		for (int i = 0; i < list.size(); i++) { 
			for (int j = 0; j < metalist.size(); j++) {
				PropertyModel propertyModel = (PropertyModel) metalist.get(j);
				if(StringUtils.isEmpty(propertyModel.getName())){
					continue;
				}
				Object object = ExcelOperationUtils.getBeanPropertyValue(
						propertyModel.getName(), list.get(i));			
				cell = ExcelOperationUtils.getPropertyValue(colNum + j,lineNum,object,propertyModel);				
				sheet.addCell(cell);
			}
			lineNum++;
		}
		return lineNum;
	}

	/**
	 * 填充表头数据
	 * @param lineNum ：行号
	 * @param sheet ：
	 * @param metalist ：表头数据
	 * @param contextMap
	 * @param startCol ：
	 * @return
	 * @throws WriteException
	 * @throws RowsExceededException
	 */
	private int fillTitle(int lineNum, WritableSheet sheet,
			List<PropertyModel> metalist, Map<String, String> contextMap,
			int startCol) throws WriteException, RowsExceededException {
		
		int maxMergeRowNum = 1;// 最大的合并行数
		int noShowRow =0; //如果此行不显示，在sheet的输出行减去1
		int showTitle=0;
		for (int j = 0; j < metalist.size(); j++) {
			PropertyModel propertyModel = (PropertyModel) metalist.get(j);			
			if(StringUtils.isEmpty(propertyModel.getTitle())){
				showTitle++;
			}			
			if(!StringUtils.isEmpty(propertyModel.getDisplayRow())){
				String str = StringUtils.replaceByContextMap(contextMap, propertyModel.getDisplayRow());
				if(!StringUtils.isEmpty(str)){
					noShowRow=-1;
					break;
				}	
			}
			int noShowCol =0; //如果此列不显示，在sheet的输出列减去1
			if(!StringUtils.isEmpty(propertyModel.getDisplayCol())){
				String str = StringUtils.replaceByContextMap(contextMap, propertyModel.getDisplayCol());
				if(StringUtils.isEmpty(str)){
					noShowCol=-1;
					continue;
				}	
			}			
			int rowNumber = propertyModel.getMergeRowNumber();// 要合并的行数
			int colNUmber = propertyModel.getMergeColumnNumber();// 要合并的列数
			maxMergeRowNum = getMaxInt(maxMergeRowNum, rowNumber);
			if (rowNumber != 1 || colNUmber != 1) {
				sheet.mergeCells(startCol, lineNum, startCol + colNUmber - 1,
						lineNum + rowNumber - 1);
			}
			sheet.addCell(new Label(startCol+noShowCol, lineNum, StringUtils.replaceByContextMap(
					contextMap, propertyModel.getTitle()),
					new ExcelCellFormat().getCellFormat(propertyModel
							.getHeaderStyleMap())));
			//设置列宽
			sheet.setColumnView(startCol, propertyModel.getColumnWithInt());
			startCol = startCol + colNUmber;
		}
		if(showTitle==metalist.size()){
			noShowRow=-1;
		}
		lineNum = lineNum + maxMergeRowNum+noShowRow;
		return lineNum;
	}

	/**
	 * 关闭资源
	 * 
	 * @param outputStream
	 * @param wwb
	 */
	private void closeResource(OutputStream outputStream, WritableWorkbook wwb) {
		if (wwb != null) {
			try {
				wwb.close();
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				wwb = null;
			}
		}
		if (outputStream != null) {
			try {
				outputStream.close();
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				outputStream = null;
			}
		}
	}
	
	
	/**
	 * 得到两个整数中最大的一个
	 * 
	 * @param a
	 * @param b
	 * @return
	 */
	private int getMaxInt(int a, int b) {
		return a > b ? a : b;
	}
}
